package 动态数组;

// 为其他类写一个动态数组的接口，包含一些常用的方法

import java.lang.Object; // 泛型继承的是这个类，是java.lang下的Object

// 方法前加不加static的区别，加了static就是静态方法，可以直接通过类名调用比如Arraylist.add(),如果没有加static，那么要调用这个方法就要先创建对象
// 动态数组要包含的方法
public class Arraylist <E> {

    // 封装成员变量

    /* 元素的数量 */
    private int size;

    /* 存放所有元素的集合 */
    private E []elements;

    /* 设置常量抛异常或者要传默认值的时候用，static的作用是保证这个常量的内存永远只有一份 */
    private static final int DEFAULT_CAPACITY = 10;
    private static final int ELEMENT_NOT_FOUND = -1;

    /* 写一个构造函数，构造函数是在new创建对象的时候用的，其中无参的构造函数是系统默认生成的，有参的构造函数需要自己写 */
    public Arraylist(int capacity){
        if (capacity <= 0){
            elements = (E[])new Object[DEFAULT_CAPACITY];
        }else {
            elements = (E[])new Object[capacity];
        }

    }
    /* 无参的构造函数，this表示调用有参的构造函数，等价于其中的参数传入capacity */
    public Arraylist(){
        this(DEFAULT_CAPACITY);
       // 等价于这种写法elements = new int[DEFAULT_CAPACITY];

    }

    /* size方法，查询元素的数量，直接返回size */
    public int size(){
        return size;
    }

    /* isEmpty方法，判断是否为空 */
    public boolean isEmpty(){
        if (size == 0){
            return true;
        }else {
            return false;
        }
    }

    /* get方法，获取数组内的元素*/
    public E get(int index){
        if (index < 0 || index >= size){
            throw new IndexOutOfBoundsException("异常提醒：你好像下标越界了，你的元素数量是:"+size);
        }else {
            return elements[index];
        }
    }

    /* set方法，设置你想要的元素，在你想要的位置 */
    public E set(int index,E element){
        if (index < 0 || index >= size){
            throw new IndexOutOfBoundsException("异常提醒：你好像下标越界了，你的元素数量是:"+size);
        }else {
            E old = elements[index];
            elements[index] = element;
            return old;
        }
    }

    /* indexOf方法，查询元素的索引,发生异常返回-1 */
    public int indexOf(E element){

        // 如果传入的element是空值的情况
        if(element == null){
            for (int i = 0;i<size;i++){
                if (elements[i] == null){
                    return i;
                }
            }
        }else {
            for (int i = 0;i < size;i++){

                // 如果不用equals比较，那么比较的就是内存地址（不建议），如果用equals比较，比较的就是具体的值。如果自定义的数据类型使用equals比较
                // 那么，要在那个数据类型的类里面重写equals，否则默认的equals还是比较的是地址。
                if (element.equals(elements[i])){
                    return i;
                }
            }
        }

        return ELEMENT_NOT_FOUND;
    }

    /* contains方法，查询数组是否包含这个元素,调用indexOf方法如果这个元素不返回-1说明存在这个元素 */
    public boolean contains(E element){
        if (indexOf(element) != ELEMENT_NOT_FOUND){
            return true;
        }else {
            return false;
        }
    }

    /* clear方法，清除所有元素,不让数组等于0的原因是因为看起来好像让数组等于0比较节省内存，但是如果你下次要往数组增加元素的话，又要向堆空间申请内存
    *  即 new 一个对象，不如用size = 0这个方法,但是如果数组内的元素比较多的话比如多于100个，那就直接让数组为空 */
    public void clear(){

        // 如果直接elements = null的话，整个数组的内存都会被销毁，这样一来又得new一个对象。
         for (int i = 0;i<size;i++){
             elements[i] = null;
         }
         size = 0;
    }

    /* add方法，在数组最后面添加元素,添加的位置等于size */
    public void add(E element) {
//         elements[size] = element;
//         size++;

        add(size,element);

    }

    /* add方法，在指定的位置添加元素 */
    public void add(int index,E element){

        ensureCapacity(size+1);

        if (index < 0 || index > size){
            throw new IndexOutOfBoundsException("异常提醒：你好像下标越界了，你的元素数量是:" + size);
        }else {
            for (int i =size-1;i>index;i--){
                elements[i+1] = elements[i];
            }
            elements[index] = element;
            size++;
        }
    }

    /* remove方法，删除指定index的元素，并返回你删的是哪个元素,同时size-- */
    public E remove(int index){
        if (index < 0 || index >= size){
            throw new IndexOutOfBoundsException("异常提醒：你好像下标越界了，你的元素数量是:" + size);
        }else {
            E old = elements[index];
            for (int i = index + 1;i < size - 1;i++ ){
                elements[i-1] = elements[i];
            }

            // 这里要先size--，然后再清空内存
            size--;
            elements[size] = null;
            return old;
        }
    }

    /* toString方法，就是打印对象的时候返回的东西 */
    public String toString(){
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("[");
        for (int i = 0;i<size;i++){
            if (i != size-1){
                stringBuilder.append(elements[i]).append(", ");
            }else {
                stringBuilder.append(elements[i]);
            }
        }
        stringBuilder.append("]");
        return stringBuilder.toString();
    }

    /* ensureCapacity方法，判断数组容量是否足够，如果不够则将数组扩容1.5倍 */
    public void ensureCapacity(int capacity){
        int oldCapacity = elements.length;
        if (oldCapacity < capacity){
            // >>1表示除以2 1+二分之一 = 1.5
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            E []new_elements = (E[])new Object[newCapacity];
            for (int i = 0;i<size;i++){
                new_elements[i] = elements[i];
            }
            elements = new_elements;
            System.out.println("原来的数组容量为："+oldCapacity+"  现在已经扩容为："+elements.length);
        }else {
            return;
        }
    }




    public static void main(String[] args) {
        
    }
}
